package cn.ztr.ymcc.service.impl;

import cn.ztr.ymcc.config.ZFBConfig;
import cn.ztr.ymcc.constance.cons;
import cn.ztr.ymcc.domain.PayFlow;
import cn.ztr.ymcc.domain.PayOrder;
import cn.ztr.ymcc.domain.PayZfb;
import cn.ztr.ymcc.dto.PaySuccessDto;
import cn.ztr.ymcc.mapper.PayFlowMapper;
import cn.ztr.ymcc.mapper.PayOrderMapper;
import cn.ztr.ymcc.result.JsonResult;
import cn.ztr.ymcc.service.IPayOrderService;
import cn.ztr.ymcc.util.AssertUtil;
import com.alibaba.fastjson.JSON;
import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.kernel.util.ResponseChecker;
import com.alipay.easysdk.payment.facetoface.models.AlipayTradePrecreateResponse;
import com.alipay.easysdk.payment.page.models.AlipayTradePagePayResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.client.producer.SendStatus;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author ztr
 * @since 2023-03-10
 */
@Service
public class PayOrderServiceImpl extends ServiceImpl<PayOrderMapper, PayOrder> implements IPayOrderService {
    @Autowired
    private ZFBConfig zfbConfig;
    @Autowired
    private PayFlowMapper payFlowMapper;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    /**
     * 用户支付
     * @param payZfb
     * @return
     */
    @Override
    public JsonResult apply(PayZfb payZfb) {

        // 1. 设置参数（全局只需设置一次）
        Factory.setOptions(zfbConfig.getOptions());
        try {
            // 2. 发起API调用（以创建当面付收款二维码为例）
            AlipayTradePagePayResponse response = Factory.Payment
                    .Page().pay(payZfb.getSubject(), payZfb.getOrderNo(),
                            payZfb.getAmount().toString(), payZfb.getCallUrl());
            // 3. 处理响应或异常
            if (ResponseChecker.success(response)) {
                System.out.println("调用成功,开启延迟消息发送");
                //4 发送延迟消息,检查用户是否完成支付 课程订单信息 , 支付信息
                SendResult sendResult = rocketMQTemplate.syncSend(
                        cons.PAY_TIMEOUT_TOPIC_ZTR + ":" + cons.PAY_TIMEOUT_TARGET_ZTR,
                        MessageBuilder.withPayload(payZfb.getOrderNo()).build(),
                        3000,
                        7
                );
                AssertUtil.isTrue(sendResult.getSendStatus()==SendStatus.SEND_OK,"延迟消息发送失败");
                log.debug(response.getBody());
                return JsonResult.me(response.getBody());
            } else {
                System.err.println("调用失败，原因：" + response.getBody());
            }
        } catch (Exception e) {
            System.err.println("调用遭遇异常，原因：" + e.getMessage());
            throw new RuntimeException(e.getMessage(), e);
        }

        return null;
    }

    /**
     * 用户支付成功后的业务
     * 1 修改支付信息中的支付状态
     * 2 添加支付流水
     * 3 修改订单信息中的支付状态
     * 4 添加课程购买记录
     * @param parameters
     */
    @Override
    public void paySuccess(Map<String, String> parameters) {
        try {
            //1 修改支付信息中的支付状态
            String orderNo = parameters.get("out_trade_no");
            PayOrder payOrder = baseMapper.selectOne(new QueryWrapper<PayOrder>().eq("order_no", orderNo));
            payOrder.setPayStatus(1);
            baseMapper.updateById(payOrder);

            //2 添加支付流水
            //2.1 获取交易时间
            String notify_time = parameters.get("notify_time");
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd mm:ss");
            //2.2 创建流水对象
            PayFlow payFlow = new PayFlow()
                    .setNotifyTime(simpleDateFormat.parse(notify_time))
                    .setSubject(parameters.get("subject"))
                    .setOutTradeNo(parameters.get("out_trade_no"))
                    .setTotalAmount(new BigDecimal(parameters.get("total_amount")));
            //2.3 添加流水
            payFlowMapper.insert(payFlow);

            //3 通过mq发送信息到订单和课程服务
            //3.1 获取购买的课程id
            String extParams = payOrder.getExtParams();
            String[] strings = extParams.split("&");
            List<Long> courseIds=new ArrayList<>();
            for (String string : strings) {
                if (string.startsWith("courseIds")){
                     Arrays.stream(string.substring(string.indexOf("=") + 1).split(","))
                             .forEach(s->courseIds.add(Long.valueOf(s)));
                     break;
                }

            }
            //3.2 封装信息
            PaySuccessDto paySuccessDto = new PaySuccessDto()
                    .setLoginId(payOrder.getUserId())
                    .setCourseOrderNo(parameters.get("out_trade_no"))
                    .setCourseIds(courseIds);
            //3.3 生产者发送同步信息
            SendResult sendResult = rocketMQTemplate.syncSend(
                    cons.PAY_SUCCESS_TOPIC_ZTR + ":" + cons.PAY_SUCCESS_TARGET_ZTR,
                    MessageBuilder.withPayload(JSON.toJSONString(paySuccessDto)).build()
            );
            AssertUtil.isTrue(sendResult.getSendStatus()== SendStatus.SEND_OK,"支付成功mq消息发送失败");
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }
}
